package js

import (
	"fmt"
	"log/slog"
	"sync"

	"github.com/charmbracelet/log"
	"github.com/dop251/goja"
	"github.com/playwright-community/playwright-go"
)

var jsPlaywright = func(vm *goja.Runtime, logger *log.Logger) *goja.Object {
	pwObj := vm.NewObject()
	var installOnce sync.Once
	slogger := slog.New(logger)
	pwObj.Set("get", func(call goja.FunctionCall) goja.Value {
		url := call.Argument(0).String()
		var installErr error
		installOnce.Do(func() {
			installErr = playwright.Install(&playwright.RunOptions{
				Browsers:        []string{"chromium"},
				DriverDirectory: "./playwright",
				Logger:          slogger,
			})
		})
		if installErr != nil {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("failed to install playwright: %v", installErr),
			})
		}

		pw, err := playwright.Run(&playwright.RunOptions{
			DriverDirectory: "./playwright",
			Logger:          slogger,
		})
		if err != nil {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("failed to start playwright: %v", err),
			})
		}
		defer pw.Stop()

		browser, err := pw.Chromium.Launch()
		if err != nil {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("failed to launch browser: %v", err),
			})
		}
		defer browser.Close()

		page, err := browser.NewPage()
		if err != nil {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("failed to create page: %v", err),
			})
		}

		resp, err := page.Goto(url, playwright.PageGotoOptions{
			WaitUntil: playwright.WaitUntilStateNetworkidle,
			Timeout:   playwright.Float(60000),
		})
		if err != nil {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("failed to navigate: %v", err),
			})
		}
		if resp != nil && resp.Status() >= 400 {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("bad status code: %d", resp.Status()),
			})
		}
		content, err := page.Content()
		if err != nil {
			return vm.ToValue(map[string]any{
				"error": fmt.Sprintf("failed to get page content: %v", err),
			})
		}
		return vm.ToValue(content)
	})
	return pwObj
}
